/**************************************************************************************************
* Title: RenderManager.cpp
* Authors: Gael Huber, Erin Mooney
* Description: Manages OpenGL rendering pipeline.
**************************************************************************************************/
#include "SmurfsRenderManager.h"

// Singleton instance
template<> RenderManager* Singleton<RenderManager>::singleton = 0;

/**************************************************************************************************
* Constructor
**************************************************************************************************/
RenderManager::RenderManager(void) {
	// Do nothing
}

/**************************************************************************************************
* Destructor
**************************************************************************************************/
RenderManager::~RenderManager(void) {
	// Do nothing
}

/**************************************************************************************************
* Initialize OpenGL
**************************************************************************************************/
void RenderManager::startUp(void) {
	// Initialize a new window
	_window = new Window();
	_window->startUp(L"SMURFS Engine", 640, 480, 16);

	// Set a black background
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);		
	
	// Define the projection type as 2D
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, (GLdouble)getWindowWidth(), (GLdouble)getWindowHeight(), 0, 0, 1);
	glMatrixMode(GL_MODELVIEW);
	glDisable(GL_DEPTH_TEST);

	// Build the display lists
	buildDisplayLists();

	// Build the font
	buildFont();
}

/**************************************************************************************************
* Shutdown
**************************************************************************************************/
void RenderManager::shutDown(void) {
	killFont();	// Destroy the font used for text rendering

	// Destroy the window
	_window->shutDown();
	delete _window;
}

/**************************************************************************************************
* Get the singleton instance
**************************************************************************************************/
RenderManager& RenderManager::getSingleton(void) { 
	assert(singleton);
	return *singleton;
}

/**************************************************************************************************
* Get the singleton pointer
**************************************************************************************************/
RenderManager* RenderManager::getSingletonPtr(void) {
	return singleton;
}

/**************************************************************************************************
* Build the display lists
**************************************************************************************************/
void RenderManager::buildDisplayLists(void) {
	// Build a pong paddle
	RenderObject obj;
	obj.data = glGenLists(1);
	glNewList(obj.data, GL_COMPILE);	// New compiled object
		glBegin(GL_QUADS);
			glVertex2f(-5.0f, -25.0f);
			glVertex2f(5.0f, -25.0f);
			glVertex2f(5.0f, 25.0f);
			glVertex2f(-5.0f, 25.0f);
		glEnd();
	glEndList();
	objectList.push_back(obj);

	// Draw the pong ball
	obj.data = glGenLists(1);
	glNewList(obj.data, GL_COMPILE);	// New compiled object
		glBegin(GL_TRIANGLE_FAN);
			GLuint radius = 5;
			glVertex2f(0.0f, 0.0f);
			for(int angle = 0; angle < 360; angle+=5) {
				glVertex2f(sin((float) angle) * radius, cos((float) angle) * radius);
			}
		glEnd();
	glEndList();
	objectList.push_back(obj);
}

/**************************************************************************************************
* Render the scene
**************************************************************************************************/
void RenderManager::renderScene(void) {
	glClear(GL_COLOR_BUFFER_BIT);	// Clear the screen

	// Print out the score
	// place the text
	glLoadIdentity();
	glTranslatef((float)getWindowWidth() / 2.0f - 30.0f, 50.0f, 0.0f);
	glRasterPos2f(0.0f, 0.0f);
	// print the score
	print(scoreString);

	// Draw to the screen
	std::vector<RenderObject*>::iterator start = drawList.begin();
	std::vector<RenderObject*>::iterator end = drawList.end();
	for(std::vector<RenderObject*>::iterator itr = start; itr != end; ++itr) {
		// Position The Cubes On The Screen
		glLoadIdentity();
		glTranslatef((GLfloat) (*itr)->screenX, (*itr)->screenY, 0.0f);
		glRotatef((*itr)->angle, 0.0f, 0.0f, 1.0f);
		glCallList((*itr)->data);
	}

	SwapBuffers(_window->getHDC());
}

/**************************************************************************************************
* Add an object to the scene
**************************************************************************************************/
void RenderManager::addToScene(RenderObject* obj) {
	drawList.push_back(obj);
}

/**************************************************************************************************
* Remove an object from the scene
**************************************************************************************************/
void RenderManager::removeFromScene(GLuint id) {
}

/**************************************************************************************************
* Build a bitmap font
**************************************************************************************************/
void RenderManager::buildFont(void) {
	HFONT font;		// windows font
	HFONT oldfont;	// for "good housekeeping"

	base = glGenLists(96);

	// create the font based on the character height, not the cell height
	font = CreateFont(-24, 0, 0, 0, FW_BOLD, false, false, false, ANSI_CHARSET, OUT_TT_PRECIS, 
		CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE|DEFAULT_PITCH, (LPCWSTR)"Courier New");

	// set the new font by replacing the old
	oldfont = (HFONT)SelectObject(_window->getHDC(), font);
	wglUseFontBitmaps(_window->getHDC(), 32, 96, base);
	SelectObject(_window->getHDC(), oldfont);
	DeleteObject(font);
}

/**************************************************************************************************
* Destroy the font
**************************************************************************************************/
void RenderManager::killFont(void) {
	glDeleteLists(base, 96);		// delete all 96 characters
}

/**************************************************************************************************
* Prints whatever comes into the method
**************************************************************************************************/
void RenderManager::print(const char* toPrint) {
	char text[256];		// holds the string to be printed
	va_list ap;			// pointer to a list of arguments

	if(toPrint == NULL) return;		// there's nothing to print

	// check to see if there are any symbols that need to be converted and convert them
	va_start(ap, toPrint);
		vsprintf(text, toPrint, ap);
	va_end(ap);

	glPushAttrib(GL_LIST_BIT);		// prevents from affecting other display lists
	glListBase(base - 32);			// sets the base character to 32

	glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);	// draws the display list text
	glPopAttrib();	// pops the bits of the display list
}

/**************************************************************************************************
* Aligns and prints out the score
**************************************************************************************************/
void RenderManager::createScoreToPrint(int player, int ai) {
	// create the string to print
	char pScore[80]; char aScore[80];
	itoa(player, pScore, 10);
	itoa(ai, aScore, 10);
	strcpy(scoreString, pScore);
	strcat(scoreString, "     ");
	strcat(scoreString, aScore);
}